package com.lechi.web.util;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.lechi.iot.netty.utils.NettyCacheUtils;
import com.lechi.web.common.alarm.AlarmRuleStrategy;
import com.lechi.web.common.utils.spring.SpringUtils;
import com.lechi.web.constants.Constants;
import com.lechi.web.service.IIotAlertRecordService;
import com.lechi.web.system.domain.IotAlertRecord;
import com.lechi.web.system.domain.IotMonitorDataBo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.util.Date;
import java.util.List;

/**
 * 指令监听器
 */
@Slf4j
public class AlarmRulesUtil {

    /**
     * Alarm rule chain.
     *
     * @param iotMonitorDataBo the iot monitor data bo
     */
    public static void alarmRuleChain(IotMonitorDataBo iotMonitorDataBo) {
        String alarmRuleKey = "AlarmRule_deviceId_sensorAliasId_" + iotMonitorDataBo.getDeviceId() + "_" + iotMonitorDataBo.getSensorAliasId();
        List<AlarmRuleStrategy> alarmRuleStrategyList = NettyCacheUtils.get(alarmRuleKey, List.class);

        // 告警开关必须打开，针对这个传感器的规则拿到遍历 触发
        if (alarmRuleStrategyList == null || alarmRuleStrategyList.isEmpty()) {
            log.debug("设备：{}，传感器：{}，获取告警规则为空, 可能没有配置告警规则！", iotMonitorDataBo.getDeviceId(), iotMonitorDataBo.getSensorAliasId());
            return;
        }

        alarmRuleStrategyList.forEach(alarmRuleStrategy -> {
            String alarmLastUpdateDate = iotMonitorDataBo.getDeviceId() + "_" + alarmRuleStrategy.getAlarmType() + "LAST_UPDATE_DATE";
            if (alarmRuleStrategy.getStatus() == null || alarmRuleStrategy.getStatus() != Constants.TRIGGER_OPEN_STATUE) {
                log.debug("设备：{}，传感器：{}，获取告警规则为空, 可能没有配置告警规则！", iotMonitorDataBo.getDeviceId(), iotMonitorDataBo.getSensorAliasId());
                return;
            }
            if (alarmRuleStrategy.ifAlarm(iotMonitorDataBo.getDoubleValue())) {
                log.info("====传感器上传值：{} 产生告警,设备告警规则：{}", iotMonitorDataBo.getDoubleValue(), JSON.toJSONString(alarmRuleStrategy));
                if (ObjectUtil.isNotEmpty(alarmRuleStrategy.getDurationTime())) {
                    Date beginTime = NettyCacheUtils.get(alarmLastUpdateDate, Date.class);
                    Long outTime = ObjectUtil.isNotEmpty(beginTime) ? (new Date().getTime() - beginTime.getTime()) / 1000 : null;
                    log.info("========告警超时时间阈值：{}秒，已经产生告警超时时间：{}秒", alarmRuleStrategy.getDurationTime() * 60, outTime);
                    if (ObjectUtil.isEmpty(beginTime)) { // 空的情况下给初始化值, 5分钟后清空
                        NettyCacheUtils.put(alarmLastUpdateDate, new Date(), alarmRuleStrategy.getDurationTime() * 60000);
                        return;
                    }
                    if (alarmRuleStrategy.ifOutTime(outTime)) {
                        NettyCacheUtils.remove(alarmLastUpdateDate);
                        addAlarmRecord(alarmRuleStrategy, iotMonitorDataBo);
                    }
                } else {
                    addAlarmRecord(alarmRuleStrategy, iotMonitorDataBo);
                }
            }
        });
    }

    private static void addAlarmRecord(AlarmRuleStrategy alarmRuleStrategy, IotMonitorDataBo iotMonitorDataBo) {
        iotMonitorDataBo.setIfAlarm(true);
        IotAlertRecord iotAlertRecord = new IotAlertRecord();
        iotAlertRecord.setSendFlag(0);
        BeanUtils.copyProperties(iotMonitorDataBo, iotAlertRecord);
        iotAlertRecord.setTriggerValue(iotMonitorDataBo.getDoubleValue());// 触发值可能是触发器的值也可能是上报值
        iotAlertRecord.setContent(alarmRuleStrategy.getMsgTemplate());
        String alarmRuleTypeKey = "AlarmRuleType_" + iotAlertRecord.getDeviceId() + "_" + iotAlertRecord.getSensorAliasId();
        if (NettyCacheUtils.get(alarmRuleTypeKey, String.class) != null) {
            return;
        }
        NettyCacheUtils.put(alarmRuleTypeKey, iotAlertRecord.getAlertType());
        SpringUtils.getBean(IIotAlertRecordService.class).insertIotAlertRecord(iotAlertRecord);
        // 添加设备告警标记
        String ifAlarmKey = iotMonitorDataBo.getDeviceId() + "_IF_ALARM";
        NettyCacheUtils.put(ifAlarmKey, true, 60000L);
    }
}
